`include "macro.v"
module DRAM (
    input wire clk,
    input wire dram_we,
    input wire [1:0] sd_sel,
    input wire [2:0] ld_sel,
    input wire [31:0] addr,
    input wire [31:0] wdin,
    output reg [31:0] rd
);

wire [31:0] raw_rdata;
reg [31:0] raw_wdata;
wire [1:0] offset = addr[1:0];

// data_mem dmem(
dram u_dram(
    .clk(clk),
    .a(addr[15:2]),
    .spo(raw_rdata),
    .we(dram_we),
    .d(raw_wdata)
);

always @(*) begin
    case (sd_sel)
        `DRAM_SB : begin
            case (offset[1:0])
                2'b00   : raw_wdata = {raw_rdata[31:8], wdin[7:0]};
                2'b01   : raw_wdata = {raw_rdata[31:16], wdin[7:0], raw_rdata[7:0]};
                2'b10   : raw_wdata = {raw_rdata[31:24], wdin[7:0], raw_rdata[15:0]};
                2'b11   : raw_wdata = {wdin[7:0], raw_rdata[23:0]};
                default : raw_wdata = wdin;
            endcase
        end
        `DRAM_SH : begin
            case(offset[1])
                1'b0    : raw_wdata = {raw_rdata[31:16], wdin[15:0]};
                1'b1    : raw_wdata = {wdin[15:0], raw_rdata[15:0]};
                default : raw_wdata = wdin;
            endcase
        end
        `DRAM_SW        : raw_wdata = wdin;
        default         : raw_wdata = wdin;
    endcase
end

always @(*) begin
    case(ld_sel)
        `DRAM_LB : begin
            case(offset[1:0])
                2'b00   : rd = {{24{raw_rdata[7]}}, raw_rdata[7:0]};
                2'b01   : rd = {{24{raw_rdata[15]}}, raw_rdata[15:8]};
                2'b10   : rd = {{24{raw_rdata[23]}}, raw_rdata[23:16]};
                2'b11   : rd = {{24{raw_rdata[31]}}, raw_rdata[31:24]};
                default : rd = 32'b0;
            endcase
        end
        `DRAM_LBU : begin
            case(offset[1:0])
                2'b00   : rd = {24'b0, raw_rdata[7:0]};
                2'b01   : rd = {24'b0, raw_rdata[15:8]};
                2'b10   : rd = {24'b0, raw_rdata[23:16]};
                2'b11   : rd = {24'b0, raw_rdata[31:24]};
                default : rd = 32'b0;
            endcase
        end
        `DRAM_LH : begin
            case(offset[1])
                1'b0    : rd = {{16{raw_rdata[15]}}, raw_rdata[15:0]};
                1'b1    : rd = {{16{raw_rdata[31]}}, raw_rdata[31:16]};
                default : rd = 32'b0;
            endcase
        end
        `DRAM_LHU : begin
            case(offset[1])
                1'b0    : rd = {16'b0, raw_rdata[15:0]};
                1'b1    : rd = {16'b0, raw_rdata[31:16]};
                default : rd = 32'b0;
            endcase
        end
        `DRAM_LW        : rd = raw_rdata;
        default         : rd = raw_rdata;
    endcase
end



endmodule